package com.bupt.kgplatform.Util;

import com.bupt.kgplatform.entity.GptTask;
import com.bupt.kgplatform.entity.http.MinioFileReq;
import com.bupt.kgplatform.entity.http.MinioFileUrlRep;
import com.bupt.kgplatform.entity.http.newsObject;
import com.bupt.kgplatform.mapper.GptTaskMapper;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.jcraft.jsch.ChannelExec;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.common.PDRectangle;
import org.apache.pdfbox.pdmodel.font.PDType0Font;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.*;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Vector;


/**
 * GLMutil
 *
 * @author zrz
 * @date 2023/12/12
 * @time 16:30
 * @Description gpt任务管理要用放到的文件管理模块
 */
@Service
public class GLMutil {

    private final static String SERVER = "10.112.203.120";
    private final static Integer PORT = 17877;
    private final static String USERNAME = "machenghao";
    private final static String PASSWORD = "Mch20010115";
    private final static String ROMOTE_PATH = "/home/machenghao/gpt_academic/private_upload/default/temp/";


    @Value("${image.save-path}")
    private String sharePath;

    @Resource
    private GptTaskMapper gptTaskMapper;
    public boolean main1(Integer gptTaskId){
        GptTask gptTask = gptTaskMapper.selectById(gptTaskId);
        String jsonString = gptTask.getDataset();
        System.out.println(jsonString);
        cleanFolder();
        deleteFilesInFolder();
        try {
            ObjectMapper objectMapper = new ObjectMapper();
            List<newsObject> newsList = objectMapper.readValue(jsonString, new TypeReference<List<newsObject>>() {});

            for (newsObject news : newsList) {
                String MM = news.getTitle() + news.getData();
                String filename = MM.replaceAll("[/:*?\"<>|]", "_") + ".pdf";
                System.out.println("开始处理" + filename + "—————————————————————————————");
                String s = checkExist(filename);
                if(s != null){
                    // s是下载的url，拿到之后开始下载
                    String s1 = downloadPDF(s, filename);
                    if(Objects.equals(s1, "PDF 下载成功！")){
                        // 下载成功，开始传送
                        T2(filename);
                        System.out.println(filename + "传送成功————————————————————————————————");
                    }
                }
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    public boolean cleanFolder(){
        String directoryPath = sharePath +  "gptTaskTemp/";
        File directory = new File(directoryPath);
        if (!directory.exists()) {
            // 如果目录不存在，则创建目录
            directory.mkdirs();

        }
        return true;
    }

    public String checkExist(String filename){
        HttpClient httpClient = HttpClientBuilder.create().build();
        String url = "http://10.112.109.177:8817/minio/getfileurl"; // 替换为你的目标 URL

        MinioFileReq minioFileReq = new MinioFileReq();
        minioFileReq.setFileName(filename);
        minioFileReq.setType("newspdf");

        // 构造请求体
        // String requestBody = "{\"key1\":\"value1\",\"key2\":\"value2\"}";

        // 构造 POST 请求
        // HttpPost httpPost = new HttpPost(url);
        // httpPost.setEntity(new StringEntity(requestBody, ContentType.APPLICATION_JSON));

        try {
            ObjectMapper objectMapper = new ObjectMapper();
            String requestBodyJson = objectMapper.writeValueAsString(minioFileReq);
            // 发送请求并获取响应
            HttpPost httpPost = new HttpPost(url);
            httpPost.setEntity(new StringEntity(requestBodyJson, ContentType.APPLICATION_JSON));

            // 发送请求并获取响应
            HttpResponse response = httpClient.execute(httpPost);
            HttpEntity responseEntity = response.getEntity();

            // 读取响应内容
            String responseString = EntityUtils.toString(responseEntity);

            // 使用 Jackson ObjectMapper 将响应内容反序列化为对象
            MinioFileUrlRep responseObject = objectMapper.readValue(responseString, MinioFileUrlRep.class);

            // 提取指定字段内容


            System.out.println("Response: " + responseString);
//            System.out.println("Specific Field: " + specificField);
            if(responseObject.getCode() == 1){
                return responseObject.getData().getFileUrl();
            }
            else{
                return null;
            }


        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }

    public String downloadPDF(String pdfUrl, String fileName) {
        //String pdfUrl = "http://10.112.109.177:9000/hetaishi/ctbto/document/CTBT-ES-2009-7_%28Annual_Report_2009%29.pdf?Content-Disposition=attachment%3B%20filename%3D%22ctbto%2Fdocument%2FCTBT-ES-2009-7_%28Annual_Report_2009%29.pdf%22&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=minio%2F20231215%2F%2Fs3%2Faws4_request&X-Amz-Date=20231215T064911Z&X-Amz-Expires=432000&X-Amz-SignedHeaders=host&X-Amz-Signature=3d368b235621056004c83ad1bfda49ab53e08ed4843cfc0462b3f10a4f5c0884";
        String savePath = sharePath +  "gptTaskTemp/" + fileName;

        try {
            URL url = new URL(pdfUrl);
            BufferedInputStream in = new BufferedInputStream(url.openStream());
            FileOutputStream fileOutputStream = new FileOutputStream(savePath);

            byte[] dataBuffer = new byte[1024];
            int bytesRead;
            while ((bytesRead = in.read(dataBuffer, 0, 1024)) != -1) {
                fileOutputStream.write(dataBuffer, 0, bytesRead);
            }

            fileOutputStream.close();
            in.close();

            return "PDF 下载成功！";
        } catch (IOException e) {
            e.printStackTrace();
            return "PDF 下载失败！";
        }
    }
    public boolean T2(String fileName){

        String localFilePath = sharePath +  "gptTaskTemp/" + fileName;

        JSch jsch = new JSch();
        try {

            Session session = jsch.getSession(USERNAME, SERVER, PORT);
            session.setPassword(PASSWORD);
            session.setConfig("StrictHostKeyChecking", "no");
            session.connect();

            ChannelSftp channelSftp = (ChannelSftp) session.openChannel("sftp");
            channelSftp.connect();

            channelSftp.put(localFilePath, ROMOTE_PATH + java.nio.file.Paths.get(localFilePath).getFileName());

            channelSftp.disconnect();
            session.disconnect();
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;

    }

    public void deleteFilesInFolder() {

        JSch jsch = new JSch();
        try {
            Session session = jsch.getSession(USERNAME, SERVER, PORT);
            session.setPassword(PASSWORD);
            session.setConfig("StrictHostKeyChecking", "no");
            session.connect();

            ChannelSftp channelSftp = (ChannelSftp) session.openChannel("sftp");
            channelSftp.connect();

            // 切换到目标文件夹
            channelSftp.cd(ROMOTE_PATH);

            // 获取目标文件夹下的文件列表
            Vector<ChannelSftp.LsEntry> files = channelSftp.ls(".");
            for (ChannelSftp.LsEntry file : files) {
                String fileName = file.getFilename();
                if (!fileName.equals(".") && !fileName.equals("..")) {
                    // 删除文件
                    channelSftp.rm(fileName);
                }
            }

            channelSftp.disconnect();
            session.disconnect();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public boolean restartService(){

        String command1 = "kill $(lsof -t -i:8111)"; // 要执行的杀死进程的命令
        String command2 = "conda activate gptac_venv && nohup python /home/machenghao/gpt_academic/main.py > /dev/null 2>&1 &";
        //String command3 = "python /home/machenghao/gpt_academic/main.py";
        try {
            JSch jsch = new JSch();
            Session session = jsch.getSession(USERNAME, SERVER, PORT);
            session.setPassword(PASSWORD);
            session.setConfig("StrictHostKeyChecking", "no");
            session.connect();

//            executeCommand(session, command1);
//            System.out.println(command1 + "执行完毕！");
            executeCommand(session, command2);
            System.out.println(command2 + "执行完毕！");
//            executeCommand(session, command3);
//            System.out.println(command3 + "执行完毕！");

            session.disconnect();
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }
    private static void executeCommand(Session session, String command) throws Exception {
        ChannelExec channel = (ChannelExec) session.openChannel("exec");
        channel.setCommand(command);
        channel.setInputStream(null);

        InputStream commandOutput = channel.getInputStream();
        channel.connect();

        BufferedReader reader = new BufferedReader(new InputStreamReader(commandOutput));
        String line;
        while ((line = reader.readLine()) != null) {
            System.out.println(line);
        }

        channel.disconnect();
    }

    private static void deleteDirectory(File directory) {
        File[] files = directory.listFiles();
        if (files != null) {
            for (File file : files) {
                if (file.isDirectory()) {
                    deleteDirectory(file);
                } else {
                    boolean deleted = file.delete();
                    if (deleted) {
                        System.out.println("Deleted file: " + file.getAbsolutePath());
                    } else {
                        System.out.println("Failed to delete file: " + file.getAbsolutePath());
                    }
                }
            }
        }

        boolean deleted = directory.delete();
        if (deleted) {
            System.out.println("Deleted directory: " + directory.getAbsolutePath());
        } else {
            System.out.println("Failed to delete directory: " + directory.getAbsolutePath());
        }
    }

    public void generatePDF(String content, String filePath) {
        try (PDDocument document = new PDDocument()) {
            PDPage page = new PDPage(PDRectangle.A4);
            document.addPage(page);

            PDPageContentStream contentStream = new PDPageContentStream(document, page);
            PDType0Font font = PDType0Font.load(document, getClass().getResourceAsStream("/font/微软雅黑.ttf"));

            float margin = 50;
            float startX = page.getMediaBox().getLowerLeftX() + margin;
            float startY = page.getMediaBox().getUpperRightY() - margin;

            String[] paragraphs = content.split("\\n{2,}");
            float fontSize = 12;
            float leading = 1.5f * fontSize; // 行间距
            float maxWidth = page.getMediaBox().getWidth() - 2 * margin; // 每行的最大宽度
            int maxCharactersPerLine = (int) (maxWidth / (fontSize / 1000)); // 每行的最大字符数量

            for (String paragraph : paragraphs) {
                List<String> lines = breakTextIntoLines(paragraph, font, fontSize, maxCharactersPerLine);

                for (String line : lines) {
                    contentStream.beginText();
                    contentStream.setFont(font, fontSize);
                    contentStream.newLineAtOffset(startX, startY);
                    contentStream.showText(line);
                    contentStream.endText();

                    startY -= leading;

                    if (startY < margin) {
                        // Reached the bottom of the page, so add a new page
                        contentStream.close();
                        page = new PDPage(PDRectangle.A4);
                        document.addPage(page);
                        contentStream = new PDPageContentStream(document, page);
                        contentStream.setFont(font, fontSize);
                        startX = page.getMediaBox().getLowerLeftX() + margin;
                        startY = page.getMediaBox().getUpperRightY() - margin;
                    }
                }

                startY -= leading; // Add extra space between paragraphs
            }

            contentStream.close();
            document.save(filePath);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private List<String> breakTextIntoLines(String text, PDType0Font font, float fontSize, int maxCharactersPerLine) throws IOException {
        List<String> lines = new ArrayList<>();
        String[] words = text.trim().split("\\s+");

        StringBuilder currentLine = new StringBuilder();
        for (String word : words) {
            if (currentLine.length() + word.length() + 1 > maxCharactersPerLine) {
                lines.add(currentLine.toString().trim());
                currentLine = new StringBuilder(word);
            } else {
                if (currentLine.length() > 0) {
                    currentLine.append(" ");
                }
                currentLine.append(word);
            }
        }

        if (currentLine.length() > 0) {
            lines.add(currentLine.toString().trim());
        }

        return lines;
    }


    public void generatePDF1(String content, String filePath) {
        try (PDDocument document = new PDDocument()) {
            PDPage page = new PDPage(PDRectangle.A4);
            document.addPage(page);

            PDPageContentStream contentStream = new PDPageContentStream(document, page);
            PDType0Font font = PDType0Font.load(document, getClass().getResourceAsStream("/font/微软雅黑.ttf"));

            float margin = 50;
            float startX = page.getMediaBox().getLowerLeftX() + margin;
            float startY = page.getMediaBox().getUpperRightY() - margin;

            String[] lines = content.split("\\r?\\n");

            float fontSize = 12;
            float leading = 1.5f * fontSize; // 行间距
            float maxWidth = page.getMediaBox().getWidth() - 2 * margin; // 每行的最大宽度

            for (String line : lines) {
                int lineLength = line.length();
                float yPosition = startY;

                while (lineLength > 0) {
                    int substringLength = getFitSubstringLength(line, maxWidth, font);
                    String substring = line.substring(0, substringLength);

                    contentStream.beginText();
                    contentStream.setFont(font, fontSize);
                    contentStream.newLineAtOffset(startX, yPosition);
                    contentStream.showText(substring);
                    contentStream.endText();

                    line = line.substring(substringLength).trim();
                    lineLength = line.length();
                    yPosition -= leading;

                    if (yPosition < margin) {
                        // Reached the bottom of the page, so add a new page
                        contentStream.close();
                        page = new PDPage(PDRectangle.A4);
                        document.addPage(page);
                        contentStream = new PDPageContentStream(document, page);
                        contentStream.setFont(font, fontSize);
                        startX = page.getMediaBox().getLowerLeftX() + margin;
                        startY = page.getMediaBox().getUpperRightY() - margin;
                        yPosition = startY;
                    }
                }
                startX = page.getMediaBox().getLowerLeftX() + margin;
                startY = page.getMediaBox().getUpperRightY() - margin;
            }

            contentStream.close();
            document.save(filePath);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }




    private int getFitSubstringLength(String text, float maxWidth, PDType0Font font) throws IOException {
        int length = text.length();
        float width = font.getStringWidth(text) / 1000 * 12;
        int substringLength = text.length();

        while (width > maxWidth) {
            substringLength--;
            width = font.getStringWidth(text.substring(0, substringLength)) / 1000 * 12;
        }

        return substringLength;
    }

    public void writeStringToPdf(String content, String filePath) throws IOException {
        PDDocument document = new PDDocument();
        PDPage page = new PDPage(PDRectangle.A4);
        document.addPage(page);
        String p1 = "D:\\Google\\arial-unicode-ms.ttf";
        PDPageContentStream contentStream = new PDPageContentStream(document, page);
        contentStream.beginText();

        contentStream.setFont(PDType0Font.load(document, getClass().getResourceAsStream("/font/微软雅黑.ttf")),12);
        contentStream.newLineAtOffset(25, 800); // 设置文本起始位置
        contentStream.showText(content);
        contentStream.endText();
        contentStream.close();

        document.save(filePath);
        document.close();
    }

}
